package me.keiwu.user.service.impl;

import me.keiwu.pub.data.ResponseV2;
import me.keiwu.pub.data.enums.NoticeType;
import me.keiwu.pub.util.DateUtil;
import me.keiwu.user.dao.CommentDao;
import me.keiwu.user.dao.NoticeDao;
import me.keiwu.user.domain.Notice;
import me.keiwu.user.rpc.ChallengeRpc;
import me.keiwu.user.service.NoticeService;
import me.keiwu.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.util.List;

/**
 * Created by kei on 05/02/2018.
 */
@Service
@Transactional
public class NoticeServiceImpl implements NoticeService {

    @Autowired
    private NoticeDao noticeDao;
    @Autowired
    private ChallengeRpc challengeRpc;
    @Autowired
    private CommentDao commentDao;
    @Autowired
    private UserService userService;



    @Override
    public Notice notice(NoticeType noticeType, Long fromUser, Long toUser, String addition, boolean redPoint) {
        Notice notice = new Notice();
        notice.setNoticeType(noticeType.getType());
        notice.setFromUser(fromUser);
        notice.setToUser(toUser);
        notice.setAddition(addition);
        notice.setHasRead(!redPoint);
        notice.setTime(DateUtil.getUnixTime());
        noticeDao.save(notice);
        return notice;
    }

    @Override
    public Notice uniqueNotice(NoticeType noticeType, Long fromUser, Long toUser, String addition, boolean redPoint) {
        Notice notice = noticeDao.findForReNotice(noticeType.getType(), fromUser, toUser);
        if (notice == null) {
            notice = new Notice();
            notice.setNoticeType(noticeType.getType());
            notice.setFromUser(fromUser);
            notice.setToUser(toUser);
        }
        notice.setAddition(addition);
        notice.setHasRead(!redPoint);
        notice.setTime(DateUtil.getUnixTime());
        noticeDao.save(notice);
        return notice;
    }

    @Override
    public Notice uniqueNotice(NoticeType noticeType, String uniqueKey, Long fromUser, Long toUser, String addition, boolean redPoint) {
        Notice notice = noticeDao.findUniqueNotice(noticeType.getType(), uniqueKey, fromUser, toUser);
        if (notice == null) {
            notice = new Notice();
            notice.setNoticeType(noticeType.getType());
            notice.setUniqueKey(uniqueKey);
            notice.setFromUser(fromUser);
            notice.setToUser(toUser);
        }
        notice.setAddition(addition);
        notice.setHasRead(!redPoint);
        notice.setTime(DateUtil.getUnixTime());
        noticeDao.save(notice);
        return notice;
    }


    @Override
    public ResponseV2 read(Long noticeId) {
        Notice notice = noticeDao.findOne(noticeId);
        if (notice == null) return ResponseV2.fail("没有该通知");

        notice.setHasRead(true);
        noticeDao.save(notice);
        return ResponseV2.ok(notice);
    }


    @Override
    public ResponseV2 readMulti(List<Long> noticeIdList) {
        noticeIdList.forEach(id -> {
            Notice notice = noticeDao.findOne(id);
            if (notice != null) {
                notice.setHasRead(true);
                noticeDao.save(notice);
            }
        });
        return ResponseV2.ok();
    }


    @Override
    public Page<Notice> list(Long userId, NoticeType noticeType, int page, int size) {
        Specification<Notice> spec = (root, query, cb) -> {
            Predicate p1 = cb.equal(root.get("noticeType"), noticeType.getType());
            Predicate p2 = cb.equal(root.get("toUser"), userId);
            return cb.and(p1, p2);
        };
        Sort sort = new Sort(Sort.Direction.DESC, "time");
        Pageable pageable = new PageRequest(page, size, sort);
        Page<Notice> list = noticeDao.findAll(spec, pageable);
        list.getContent().forEach(n -> {
            n.setFromUserInfo(userService.getUserInfo(n.getFromUser()));
            n.setToUserInfo(userService.getUserInfo(n.getToUser()));
        });
        return list;
    }


    @Override
    public boolean checkNotRead(Integer noticeType, Long userId) {
        return noticeDao.countNotReadByNoticeType(noticeType, userId) > 0;
    }


    @Override
    public Page<Notice> unreadChallengeNoticeList(int page, int size, int startTime, int endTime) {
        NoticeType noticeType = NoticeType.CHALLENGE;
        Specification<Notice> spec = (root, query, cb) -> {
            Predicate p1 = cb.equal(root.get("noticeType"), noticeType.getType());
            Predicate p2 = cb.equal(root.get("hasRead"), false);
            Predicate p3 = cb.greaterThanOrEqualTo(root.get("time"),startTime);
            Predicate p4 = cb.lessThan(root.get("time"),endTime);
            return cb.and(cb.and(cb.and(p1,p2),p3),p4);
        };

        Sort sort = new Sort(Sort.Direction.DESC, "time");
        Pageable pageable = new PageRequest(page, size, sort);
        Page<Notice> list = noticeDao.findAll(spec, pageable);
//        list.getContent().forEach(n -> {
//            n.setFromUserInfo(userService.getUserInfo(n.getFromUser()));
//            n.setToUserInfo(userService.getUserInfo(n.getToUser()));
//        });
        return list;
    }
}
